/**
 * 蓝牙核心适配器
 * 提供统一的蓝牙操作接口，自动适配H5和其他平台
 */

import { 
  isH5Platform, 
  isWebBluetoothSupported, 
  createError, 
  createSuccess, 
  formatDeviceInfo,
  formatServiceInfo,
  formatCharacteristicInfo,
  checkRequiredParams,
  withTimeout,
  arrayBuffer2HexString,
  hexString2ArrayBuffer,
  createSmartDeviceRequestOptions
} from './utils.js'

import { 
  ERROR_CODES, 
  BLUETOOTH_STATE, 
  CONNECTION_STATE, 
  DEFAULT_CONFIG,
  PLATFORMS
} from './constants.js'

/**
 * 蓝牙核心适配器类
 */
export class BluetoothCore {
  constructor() {
    this.platform = this.getCurrentPlatform()
    this.isH5 = isH5Platform()
    this.state = {
      adapterInitialized: false,
      discovering: false,
      devices: new Map(),
      connectedDevices: new Map(),
      services: new Map(),
      characteristics: new Map()
    }
    
    // 事件监听器
    this.listeners = {
      deviceFound: [],
      stateChange: [],
      characteristicValueChange: []
    }
    
    // H5平台特有属性
    if (this.isH5) {
      this.bluetooth = null
      this.checkWebBluetoothSupport()
    }
  }

  /**
   * 获取当前平台
   */
  getCurrentPlatform() {
    // #ifdef H5
    return PLATFORMS.H5
    // #endif
    
    // #ifdef MP-WEIXIN
    return PLATFORMS.MP_WEIXIN
    // #endif
    
    // #ifdef MP-ALIPAY
    return PLATFORMS.MP_ALIPAY
    // #endif
    
    // #ifdef MP-BAIDU
    return PLATFORMS.MP_BAIDU
    // #endif
    
    // #ifdef MP-TOUTIAO
    return PLATFORMS.MP_TOUTIAO
    // #endif
    
    // #ifdef MP-QQ
    return PLATFORMS.MP_QQ
    // #endif
    
    // #ifdef MP-360
    return PLATFORMS.MP_360
    // #endif
    
    // #ifdef APP-PLUS
    return PLATFORMS.APP_PLUS
    // #endif
    
    return PLATFORMS.H5
  }

  /**
   * 检查Web Bluetooth支持
   */
  checkWebBluetoothSupport() {
    if (!isWebBluetoothSupported()) {
      console.warn('Web Bluetooth API is not supported in this browser')
    } else {
      this.bluetooth = navigator.bluetooth
    }
  }

  /**
   * 初始化蓝牙适配器
   */
  async openBluetoothAdapter(options = {}) {
    try {
      // 如果已经初始化且不强制重新初始化，检查当前状态
      if (this.state.adapterInitialized && !options.force) {
        // 检查适配器是否仍然可用
        const stateResult = await this.getBluetoothAdapterState({ _internal: true })
        if (stateResult.errCode === ERROR_CODES.OK) {
          // 适配器仍然可用，返回成功
          return createSuccess()
        } else {
          // 适配器不可用，需要重新初始化
          this.state.adapterInitialized = false
        }
      }

      if (this.isH5) {
        return await this._openBluetoothAdapterH5(options)
      } else {
        return await this._openBluetoothAdapterNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_AVAILABLE, error.message)
    }
  }

  /**
   * H5平台初始化蓝牙适配器
   */
  async _openBluetoothAdapterH5(options) {
    if (!this.bluetooth) {
      return createError(ERROR_CODES.WEB_BLUETOOTH_NOT_SUPPORTED)
    }

    try {
      // 检查蓝牙可用性
      const available = await this.bluetooth.getAvailability()
      if (!available) {
        return createError(ERROR_CODES.BLUETOOTH_NOT_AVAILABLE)
      }

      this.state.adapterInitialized = true
      this._triggerStateChange(BLUETOOTH_STATE.POWERED_ON)
      
      return createSuccess()
    } catch (error) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_AVAILABLE, error.message)
    }
  }

  /**
   * 原生平台初始化蓝牙适配器
   */
  async _openBluetoothAdapterNative(options) {
    return new Promise((resolve) => {
      uni.openBluetoothAdapter({
        ...options,
        success: (res) => {
          this.state.adapterInitialized = true
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.BLUETOOTH_NOT_AVAILABLE, err.errMsg))
        }
      })
    })
  }

  /**
   * 关闭蓝牙适配器
   */
  async closeBluetoothAdapter(options = {}) {
    try {
      if (!this.state.adapterInitialized) {
        return createError(ERROR_CODES.BLUETOOTH_NOT_INIT)
      }

      if (this.isH5) {
        return await this._closeBluetoothAdapterH5(options)
      } else {
        return await this._closeBluetoothAdapterNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台关闭蓝牙适配器
   */
  async _closeBluetoothAdapterH5(options) {
    // 断开所有连接
    for (const [deviceId, device] of this.state.connectedDevices) {
      if (device.gatt && device.gatt.connected) {
        device.gatt.disconnect()
      }
    }

    // 停止搜索
    if (this.state.discovering) {
      // H5平台的搜索会在requestDevice调用结束后自动停止
      this.state.discovering = false
    }

    // 清理状态
    this.state.adapterInitialized = false
    this.state.devices.clear()
    this.state.connectedDevices.clear()
    this.state.services.clear()
    this.state.characteristics.clear()

    this._triggerStateChange(BLUETOOTH_STATE.POWERED_OFF)
    
    return createSuccess()
  }

  /**
   * 原生平台关闭蓝牙适配器
   */
  async _closeBluetoothAdapterNative(options) {
    return new Promise((resolve) => {
      uni.closeBluetoothAdapter({
        ...options,
        success: (res) => {
          this.state.adapterInitialized = false
          this.state.devices.clear()
          this.state.connectedDevices.clear()
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 获取蓝牙适配器状态
   */
  async getBluetoothAdapterState(options = {}) {
    // 允许在内部调用时跳过初始化检查
    if (!this.state.adapterInitialized && !options._internal) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_INIT)
    }

    if (this.isH5) {
      return await this._getBluetoothAdapterStateH5(options)
    } else {
      return await this._getBluetoothAdapterStateNative(options)
    }
  }

  /**
   * H5平台获取蓝牙适配器状态
   */
  async _getBluetoothAdapterStateH5(options) {
    try {
      const available = await this.bluetooth.getAvailability()
      return createSuccess({
        available,
        discovering: this.state.discovering
      })
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * 原生平台获取蓝牙适配器状态
   */
  async _getBluetoothAdapterStateNative(options) {
    return new Promise((resolve) => {
      uni.getBluetoothAdapterState({
        ...options,
        success: (res) => resolve(createSuccess(res)),
        fail: (err) => resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
      })
    })
  }

  /**
   * 开始搜寻附近的蓝牙外围设备
   */
  async startBluetoothDevicesDiscovery(options = {}) {
    if (!this.state.adapterInitialized) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_INIT)
    }

    if (this.state.discovering) {
      return createError(ERROR_CODES.DISCOVERY_ALREADY_STARTED)
    }

    if (this.isH5) {
      return await this._startBluetoothDevicesDiscoveryH5(options)
    } else {
      return await this._startBluetoothDevicesDiscoveryNative(options)
    }
  }

  /**
   * H5平台开始搜寻设备
   */
  async _startBluetoothDevicesDiscoveryH5(options) {
    try {
      // H5平台通过requestDevice来搜索设备，这里先标记为搜索状态
      this.state.discovering = true
      return createSuccess()
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * 原生平台开始搜寻设备
   */
  async _startBluetoothDevicesDiscoveryNative(options) {
    return new Promise((resolve) => {
      uni.startBluetoothDevicesDiscovery({
        ...options,
        success: (res) => {
          this.state.discovering = true
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 停止搜寻附近的蓝牙外围设备
   */
  async stopBluetoothDevicesDiscovery(options = {}) {
    if (!this.state.adapterInitialized) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_INIT)
    }

    if (!this.state.discovering) {
      return createError(ERROR_CODES.DISCOVERY_NOT_STARTED)
    }

    if (this.isH5) {
      return await this._stopBluetoothDevicesDiscoveryH5(options)
    } else {
      return await this._stopBluetoothDevicesDiscoveryNative(options)
    }
  }

  /**
   * H5平台停止搜寻设备
   */
  async _stopBluetoothDevicesDiscoveryH5(options) {
    this.state.discovering = false
    return createSuccess()
  }

  /**
   * 原生平台停止搜寻设备
   */
  async _stopBluetoothDevicesDiscoveryNative(options) {
    return new Promise((resolve) => {
      uni.stopBluetoothDevicesDiscovery({
        ...options,
        success: (res) => {
          this.state.discovering = false
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * H5平台请求设备访问权限
   */
  async requestDevice(options = {}) {
    if (!this.isH5 || !this.bluetooth) {
      return createError(ERROR_CODES.WEB_BLUETOOTH_NOT_SUPPORTED)
    }

    try {
      // 使用智能选项处理，自动添加常见服务到optionalServices
      let requestOptions = createSmartDeviceRequestOptions(options)
      
      // Web Bluetooth API支持两种方式：
      // 1. 使用filters指定特定设备
      // 2. 使用acceptAllDevices: true接受所有设备
      
      // 如果没有提供filters且没有设置acceptAllDevices，则默认接受所有设备
      if (!requestOptions.filters && !requestOptions.acceptAllDevices) {
        requestOptions.acceptAllDevices = true
      }
      
      // 如果同时提供了filters和acceptAllDevices，优先使用filters
      if (requestOptions.filters && requestOptions.acceptAllDevices) {
        delete requestOptions.acceptAllDevices
      }
      
      const device = await this.bluetooth.requestDevice(requestOptions)
      const deviceInfo = formatDeviceInfo(device, this.platform)
      
      // console.log('[JZ-H5-Bluetooth] Device selected:', {
      //   id: device.id,
      //   name: device.name,
      //   hasGatt: !!device.gatt,
      //   optionalServices: requestOptions.optionalServices
      // })
      
      // 缓存设备和授权的服务信息
      const deviceCacheInfo = {
        device: device,
        authorizedServices: new Set(),
        requestOptions: requestOptions
      }
      
      // 记录授权访问的服务UUID
      if (requestOptions.optionalServices) {
        requestOptions.optionalServices.forEach(serviceUuid => {
          deviceCacheInfo.authorizedServices.add(serviceUuid.toLowerCase())
        })
      }
      
      // 如果使用了filters，也可能包含服务授权
      if (requestOptions.filters) {
        requestOptions.filters.forEach(filter => {
          if (filter.services) {
            filter.services.forEach(serviceUuid => {
              deviceCacheInfo.authorizedServices.add(serviceUuid.toLowerCase())
            })
          }
        })
      }
      
      // 缓存设备信息（使用设备ID作为key）
      this.state.devices.set(device.id, device)
      this.state.devices.set(`${device.id}_cache_info`, deviceCacheInfo)
      
      // 也使用formatted的deviceId作为备用key（防止ID格式不一致）
      if (deviceInfo.deviceId !== device.id) {
        this.state.devices.set(deviceInfo.deviceId, deviceCacheInfo)
      }
      
      // console.log('[JZ-H5-Bluetooth] Device cached with keys:', [device.id, deviceInfo.deviceId])
      // console.log('[JZ-H5-Bluetooth] Authorized services:', Array.from(deviceCacheInfo.authorizedServices))
      
      // 触发设备发现事件
      this._triggerDeviceFound(deviceInfo)
      
      return createSuccess({ device: deviceInfo })
    } catch (error) {
      console.error('[JZ-H5-Bluetooth] Device selection error:', error)
      
      if (error.name === 'NotFoundError') {
        return createError(ERROR_CODES.DEVICE_NOT_FOUND, '未选择设备或没有找到匹配的设备，请重新尝试选择设备')
      } else if (error.name === 'SecurityError') {
        return createError(ERROR_CODES.PERMISSION_DENIED, `权限被拒绝: ${error.message}`)
      } else if (error.name === 'NotAllowedError') {
        return createError(ERROR_CODES.USER_CANCELLED, '用户取消了设备选择，可重新点击进行设备选择')
      } else if (error.name === 'NotSupportedError') {
        return createError(ERROR_CODES.WEB_BLUETOOTH_NOT_SUPPORTED, '当前浏览器不支持Web Bluetooth API')
      } else if (error.name === 'InvalidStateError') {
        return createError(ERROR_CODES.BLUETOOTH_NOT_AVAILABLE, '蓝牙适配器状态无效，请检查蓝牙是否开启')
      } else {
        return createError(ERROR_CODES.FAIL, `设备选择失败: ${error.message}`)
      }
    }
  }

  /**
   * 获取在蓝牙模块生效期间所有已发现的蓝牙设备
   */
  async getBluetoothDevices(options = {}) {
    if (!this.state.adapterInitialized) {
      return createError(ERROR_CODES.BLUETOOTH_NOT_INIT)
    }

    if (this.isH5) {
      return await this._getBluetoothDevicesH5(options)
    } else {
      return await this._getBluetoothDevicesNative(options)
    }
  }

  /**
   * H5平台获取已发现的设备
   */
  async _getBluetoothDevicesH5(options) {
    const devices = Array.from(this.state.devices.values()).map(device => 
      formatDeviceInfo(device, this.platform)
    )
    return createSuccess({ devices })
  }

  /**
   * 原生平台获取已发现的设备
   */
  async _getBluetoothDevicesNative(options) {
    return new Promise((resolve) => {
      uni.getBluetoothDevices({
        ...options,
        success: (res) => resolve(createSuccess(res)),
        fail: (err) => resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
      })
    })
  }

  /**
   * 触发状态变化事件
   */
  _triggerStateChange(state) {
    this.listeners.stateChange.forEach(listener => {
      try {
        listener({ state })
      } catch (error) {
        console.error('Error in state change listener:', error)
      }
    })
  }

  /**
   * 触发设备发现事件
   */
  _triggerDeviceFound(device) {
    this.listeners.deviceFound.forEach(listener => {
      try {
        listener({ devices: [device] })
      } catch (error) {
        console.error('Error in device found listener:', error)
      }
    })
  }

  /**
   * 触发特征值变化事件
   */
  _triggerCharacteristicValueChange(data) {
    this.listeners.characteristicValueChange.forEach(listener => {
      try {
        listener(data)
      } catch (error) {
        console.error('Error in characteristic value change listener:', error)
      }
    })
  }

  /**
   * 添加事件监听器
   */
  addEventListener(type, listener) {
    if (this.listeners[type]) {
      this.listeners[type].push(listener)
    }
  }

  /**
   * 移除事件监听器
   */
  removeEventListener(type, listener) {
    if (this.listeners[type]) {
      const index = this.listeners[type].indexOf(listener)
      if (index > -1) {
        this.listeners[type].splice(index, 1)
      }
    }
  }

  /**
   * 清除所有事件监听器
   */
  clearEventListeners() {
    Object.keys(this.listeners).forEach(type => {
      this.listeners[type] = []
    })
  }
}

// 导出单例实例
export const bluetoothCore = new BluetoothCore()
